package vip.yyzhu.redisadmin.api.key.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Response;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import redis.clients.jedis.Transaction;
import vip.yyzhu.redisadmin.aop.permissions.AuthUnique;
import vip.yyzhu.redisadmin.aop.verifyKeyType.VerifyKeyType;
import vip.yyzhu.redisadmin.jopo.ResData;
import vip.yyzhu.redisadmin.jopo.ResJson;
import vip.yyzhu.redisadmin.redis.RedisList;
import vip.yyzhu.redisadmin.util.Tool;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping(value = "/api/key/set", produces = "application/json;charset=UTF-8")
@SuppressWarnings("all")
public class SetController {
    @Autowired
    RedisList redisList;
    @Autowired
    Tool tool;
    ObjectMapper mapper = new ObjectMapper();

    /**
     * 添加
     * @param key set的key
     * @param values 数组
     * @return {"redis":"", "map":{"key":a, "values":v, "repeat":v, "add":v, }}
     */
    @VerifyKeyType(value = "set", empty = true)
    @RequestMapping(value = "/sadd", method = RequestMethod.POST)
    public Object set(HttpServletRequest request,
                      @RequestParam String key,
                      @RequestParam String values) throws Exception {
        val jedis = tool.getJedis(request);
        //json转list
        String[] list = mapper.readValue(values, String[].class);
        // 需要添加的
        List<String> success = new ArrayList();
        // 已经存在的
        List<String> repeat = new ArrayList();
        for (String s : list) {
            if (jedis.sismember(key, s)) {
                repeat.add(s);
            } else {
                success.add(s);
            }
        }
        if (success.size() > 0) {
            String[] adds = new String[success.size()];
            success.toArray(adds);
            jedis.sadd(key, adds);
        }
        Map map = new HashMap();
        map.put("key", key);
        map.put("repeat", repeat);
        map.put("success", success);
        ResData res = new ResData(map);
        return new ResJson(200, "成功", res);
    }

    /**
     * 删除set指定key
     * @param key set的key
     * @param value 要删除的value
     * @return {"redis":"", "map":{"key":a, "value":v}}
     */
    @VerifyKeyType("set")
    @RequestMapping(value = "/srem", method = RequestMethod.POST)
    public Object srem(HttpServletRequest request,
                       @RequestParam String key,
                       @RequestParam String value) throws Exception {
        val jedis = tool.getJedis(request);
        Long srem = jedis.srem(key, value);
        Map map = new HashMap();
        map.put("key", key);
        map.put("value", value);
        ResData res = new ResData(map);
        res.setRedis(srem);
        return new ResJson(200, "成功", res);
    }

    /**
     * 修改set指定key
     * @param key set的key
     * @param value 要删除的value
     * @return {"redis":"", "map":{"key":a, "value":v}}
     */
    @VerifyKeyType("set")
    @RequestMapping(value = "/sedit", method = RequestMethod.POST)
    public Object sedit(HttpServletRequest request,
                       @RequestParam String key,
                        @RequestParam String value,
                        @RequestParam String oldValue) throws Exception {
        val jedis = tool.getJedis(request);
        Boolean sismember = jedis.sismember(key, oldValue);
        if(!sismember){
            return new ResJson(4000, "修改失败", new ResData("数据可能已经被改变，请刷新后重新发起修改操作"));
        }
        if (value.equals(oldValue)) {
            return new ResJson(4000, "没有变化");
        }
        if(jedis.sismember(key, value)){
            return new ResJson(4000, "修改失败", new ResData("目标"+value+"已存在，你可以选择删除等操作"));
        }
        // 开启jedis事务
        Transaction multi=jedis.multi();
        try {
            multi.srem(key, oldValue);
            Response<Long> sadd1 = multi.sadd(key, value);
        } catch (Exception e) {
            //redis事务回滚
            multi.discard();
            e.printStackTrace();
            return new ResJson(4000, "修改失败", new ResData("已为您回滚事务"));
        }
        List<Object> exec = multi.exec();
        Map map = new HashMap();
        map.put("key", key);
        map.put("oldValue", oldValue);
        map.put("value", value);
        ResData res = new ResData(map);
        res.setRedis(exec);
        return new ResJson(200, "成功", res);
    }



    /**
     * 使用游标获取kes列表
     * @param cursor 游标
     * @param size 一页的数量
     * @param match 模糊搜索
     * @return {"map":{"total":10, "sift":5, "cursor":"0"}, "list":[]}
     */
    @VerifyKeyType("set")
    @RequestMapping(value = "/sscan", method = RequestMethod.POST)
    public Object scan(HttpServletRequest request,
                       @RequestParam String key,
                       @RequestParam String cursor,
                       @RequestParam(required = false, defaultValue = "100") int size,
                       @RequestParam(required = false, defaultValue = "100") int page_size,
                       @RequestParam(required = false) String match) {
        val jedis = tool.getJedis(request);

        ScanParams scanParams = new ScanParams();
        scanParams.count(page_size < 200 ? 200 : page_size);//页数
        if (match != null && !match.equals("")) {
            scanParams.match(match);
        }

        String new_cursor = cursor;
        List<String> list = new ArrayList();
        //  加载到size的数量
        while (list.size() < size){
            ScanResult<String> scan = jedis.sscan(key, new_cursor, scanParams);
            new_cursor = scan.getStringCursor();
            list.addAll(scan.getResult());
            if(new_cursor.equals("0")){
                break;
            }
        }
        Map map = new HashMap();
        map.put("total", jedis.scard(key));
        map.put("cursor", new_cursor);
        ResData res = new ResData();
        res.setList(list);
        res.setMap(map);
        return new ResJson(200, "成功", res);
    }
}
